;  Base file for project 4
;  ECE 2504 fall 2007
;  Kevin Green

	list P=16F84
	include	P16F84.INC
; turn off the watchdog timer to fix odd behavior on long runs.
 	__CONFIG _HS_OSC&_WDT_OFF&_PWRTE_ON&_CP_OFF 

; Define the direction bit types
f	equ	1
w	equ	0



; Define the data storage locations
; These definitions at 0x20-0x29 are supplied to the user and must not be modified
; The TAs will use the locations for the variables (avg through n0) as part
; of the validation, so they must be located in locations 0x20 through 0x29.
			org	0x20
avg			res	1	;the average of the last 4 sensor readings

asciiavg		res 	3	;the decimal equivalent of the average, in ASCII
							;one byte for the ASCII character for each decimal digit.


inval			res 	1	;the last 4-bit sensor value read, its upper 4 bits are 0
					;after the interrupt returns. 

semaphore		res	1	;an indicator that a new sensor value has been loaded into inval

;  The four 8-bit values used to compute the average, with n3 being the most recent and n0 being
;  the least recent.
n3			res 1
n2			res	1
n1			res	1
n0			res	1

v3	equ	0x33	;monitor n values by name. just makes things easier.
v2	equ 0x32
v1	equ 0x31
v0	equ 0x30

asciiOnes	equ 0x34	;monitor ascii vals
asciiTens	equ 0x34
asciiHundreds	equ 0x36 

invalMonitor	equ 0x37 ; monitors value in 'inval'
avgMonitor	equ	0x38	; monitors value in 'avg'

; you may add more data storage declarations here.

chunk	equ 0x2A	;This keeps track of which part of the byte we're reading
					;For example a value of all 1's indicates reading the 4 MSBits (left half) 
					;0's indicate LSBits (right half)
					;So,  chunk = 1111,1111 = reading in [1111],XXXX - MSBs
					;& chunk  = 0000,0000	= reading in XXXX,[1111] - LSBs

scratch equ 0x2B	;where we are storing the inputs. used with 'chunk' 
					;to decide which half of a byte we're reading

carryReg	equ 0x2D	;used for calculating the average. 
						;stores accumulated carries when adding.

temp equ 0x2E			;more temporary variables

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DO NOT CHANGE THIS SECTION
; start defining the program
; jump around the interrupt handler return to the main program
	org	0x0
start		bsf		INTCON,GIE
		bsf		INTCON,INTE
		clrf	semaphore
		goto	main

; handler is supplied to the user
; it reads a 4-bit value from PORTA and stores it in location
; "inval"
; in this assignment, we are assuming that 200 
; cycles passes between interrupts
; do not modify the handler code
	org 0x4
handler	nop
		movf	PORTA,w
		andlw	0x0F			; w = I3,I2,I1,I0, 1111
		movwf	inval			;inval = w
		movwf 	invalMonitor
		bsf		semaphore,0
		bcf		INTCON,INTF
		retfie
; end of section not to change
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; beginning of the "real" program
; start by clearing all of the variables to 0
	org 0x100
main
		clrf 	avg
		clrf 	asciiavg
		clrf	asciiavg+1
		clrf	asciiavg+2
		clrf	n3
		clrf	n2
		clrf	n1
		clrf	n0



;		the program sits in this loop waiting for interrupts
;		when a new input value is available, semaphore is set to 1
loop	btfss	semaphore,0
		goto	loop
;		at this point, the location "inval" will have the last
;       	4-bit sensor value read from port A
		bcf		semaphore,0


 goto CHECK	;main part of program below.


;-------------------------------------------------------------------------------
;Sub 'AVG', This computes the binary average and saves it

AVG
	clrw			;clear w
	clrf carryReg	;clear carry reg

;add up all the registers
	movfw v0 ;start with first value
	
	;add next register	
	addwf	v1,w	;save to w
	;check if there was a carry
	btfsc	STATUS,0	;if CARRY bit (bit 0) of status is 1
		incf carryReg	;increment the carry register

	;add next register	
	addwf	v2,w	;save to w
	;check if there was a carry
	btfsc	STATUS,0	;if CARRY bit (bit 0) of status is 1
		incf carryReg	;increment the carry register

	;add next register	
	addwf	v3,w	;save to w
	;check if there was a carry
	btfsc	STATUS,0	;if CARRY bit (bit 0) of status is 1
		incf carryReg	;increment the carry register

	;ok so carryReg and W contain the new 16 bit sum. Now to divide
	
	
	;divide by 4 = 2 shifts R with carry

;repeat 2x	
	;first, shift w to the right
	movwf temp	;save w to temp
	rrf temp,f	;rotate temp and save to w
	
	;now check if the carry was 1, and set W's bit to the carry
	
	;movwf	temp	;save w to temp
	;IF CARRY = 1
	btfsc carryReg,0	;check carry bit, skip next line if 0
	bsf	temp,7			;set the approriate MSB in W to result of the shift IN from carryReg	
	
	;IF CARRY = 0
	btfss carryReg,0	;check carry bit, skip next line if 0
	bcf	temp,7			;set the approriate MSB in W to result of the shift IN from carryReg	



	;first, shift w to the right
	;movwf temp	;save w to temp
	rrf temp,f	;rotate temp and save to w
	
	;now check if the carry was 1, and set W's bit to the carry
	
	;movwf	temp	;save w to temp

	;IF CARRY = 1
	btfsc carryReg,1	;check carry bit, skip next line if 0
	bsf	temp,7			;set the approriate MSB in W to result of the shift IN from carryReg	
	
	;IF CARRY = 0
	btfss carryReg,1	;check carry bit, skip next line if 0
	bcf	temp,7			;set the approriate MSB in W to result of the shift IN from carryReg	



	movfw	temp	;move temp to W

	

	;W now contains the binary average.
	movwf	avg		;set avg = W
	movwf	avgMonitor	;monitors the value so I can tell what it is for debugging

	return

;-------------------------------------------------------------------------------


;-------------------------------------------------------------------------------
;Sub 'TOASCII', This converts

TOASCII

i	equ 0x40	;temp counter
x 	equ 0x41	;count up!
i2  equ 0x42 	;secondary counter. corrects adding problem.

	incf x,f;

	movlw	0x08;set counter
	movwf	i2		;secondary = counter, but ahead a bit.
	;decf	i2,f	;
	movwf	i	;set i to counter;
	
	;set temp to contain binary avg
	movfw 	avg	;
	movwf	temp;

	;clear this guys
	clrf asciiOnes		;ones/tens
	clrf asciiHundreds	;hundreds

shiftloop
	
	rlf asciiHundreds,f		;shift hundreds left
						;set hundreds[0] = tens/ones[7]
	bcf asciiHundreds,0	    	;clearn hundreds[0]
	btfsc asciiOnes,7			;if tens/ones[7] is 1
		bsf asciiHundreds,0		;then set hundreds[0] to 1
	
	rlf asciiOnes,f			;shift tens/ones left
						;set tens/ones[0] = temp[7]
	bcf asciiOnes,0	    	;clean ones[0]
	btfsc temp,7			;if temp[7] is 1
		bsf asciiOnes,0		;then set ones[0] to 1
		
	rlf	temp,f				;shift temp left
	bcf	temp,0				;set temp[0] = 0
	
	decfsz i2			;prevent adding on last shift cycle
		goto ONES
	goto HUNDREDS		;skip to end if no more adding is needed.		
					
ONES	
						;check if ones>=5. 
	movfw asciiOnes			;w <-tens/ones
	andlw	0x0F			;w <- w AND 0x0F - save ones only.
	sublw	0x04			;w <- w - 4
	
	btfsc	STATUS,0			;if bit test STATUS[0] == 1 (ones > 4), else goto skip to tens
		goto TENS				
						;add 3 to ones.
	movlw	0x03				;w <- 3;
	addwf	asciiOnes,f			;tens/ones <- w+tens/ones (add 3 to f)			
	btfsc	STATUS,0			;if bit test status[0] ==1 (overflow adding)
		incf asciiHundreds,f		;increment hundreds


TENS 					;check if tens>=5. 
	movfw 	asciiTens 		;w <-tens/ones
	andlw 	0xF0			;w <- w AND 0xF0 - save tens only.
	sublw 	0x40			;w <- w - 0x40
		
	btfsc STATUS,0				;if bit test STATUS[0] == 1 (tens > 4), if not, go to hundreds
		goto HUNDREDS	
	
							;add 3 to tens.
	movlw 0x30					;w <- 0x30;
	addwf asciiTens,f			;tens/ones <- w + tens/ones (add 3 to f)			
	btfsc STATUS,0				;if bit test status[0] ==1 (overflow adding)
		incf asciiHundreds,f		;increment hundreds

HUNDREDS nop			;chill


	incf	x,f			;keep track of loopsss

	decfsz	i			;decrement i;
		goto shiftloop


;save values to right spot
	movfw 	asciiOnes 		;w <-ones
	andlw 	0x0F			;w <- w AND 0x0F - save ib es only.
	addlw	0x30;
	movwf	asciiavg+2		;make ascii+2


	movfw 	asciiTens 		;w <-tens
	andlw 	0xF0			;w <- w AND 0xF0 - save tens only.
	movwf asciiavg+1		;save tens to asciiavg+1
	swapf asciiavg+1,w		;make them in the right place.
	addlw	0x30;
	movwf	asciiavg+1		;make ascii

	
	movfw 	asciiHundreds	;w <-hundreds
	addlw	0x30;
	movwf asciiavg		;save hundreds to asciiavg

 return
;-----------------------------------------------------------


;-------------------------------------------------------------------------------
;Sub 'THEN', called when we have a complete 8-bit byte saved

THEN		;subroutine for IF statement

;save second chunk of byte
 btfsc	inval,3	;test bit 3 or I3
	bsf	scratch,7;

 btfsc inval,2	;bit 2, I2
	bsf scratch,6;

 btfsc inval,1	;bit 1, I1
	bsf scratch,5;

 btfsc inval,0	;bit 0, I0
	bsf scratch,4;


;if we have a complete byte, then insert into n3, 
;move down the n values and drop last n value

	movfw v1	;move n1 down 
	movwf v0
	movwf n0

	movfw v2	;move n2 down
	movwf v1
	movwf n1

	movfw v3	;move n3 down
	movwf v2
	movwf n2

	;push new scratch value into n3

	movfw scratch	;save to w
	movwf v3		;save w to v3/n3
	movwf n3		
	

;subroutine:	
	call AVG	;compute the average
;end sub	

	;now we have computed the binary average (can't be more than 0xFF);

;subroutine:
	call TOASCII	
;end sub

;clear scratch to all 0's
	clrf scratch
	clrw ;clear w
 return
;-------------------------------------------------------------------------------



;-------------------------------------------------------------------------------
;Sub 'ELS', called when we have first half of the byte to save

ELS		;subroutine for IF statement

 btfsc	inval,3	;test bit 3 or I3
	bsf	scratch,3;

 btfsc inval,2	;bit 2, I2
	bsf scratch,2;

 btfsc inval,1	;bit 1, I1
	bsf scratch,1;

 btfsc inval,0	;bit 0, I0
	bsf scratch,0;

 return
;-------------------------------------------------------------------------------

CHECK

;first check to see if we have a complete byte
 btfsc	chunk,0;skip sub routine if chunk is all 1's
	call THEN	;IF Above, go to THEN : save second half of byte and process
 btfss	chunk,0
	call ELS	;else - save first half of byte

;toggle chunk bit (complement)
	comf chunk



;       	end of user subroutines, return to the loop waiting for the next interrupt
; 		the values of your variables will be verified at this second goto loop statement
done		goto	loop


; 	you may insert code here too if you wish
;	This is a good place to put your subroutines.
					

					

		
		end
